package legumes.server.admin.tools;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import legumes.server.dal.DALLegumesServicesImpl;
import legumes.shared.domain.CivilityEnum;
import legumes.shared.domain.Customer;
import legumes.shared.domain.CustomerRole;
import legumes.shared.domain.HomePlaceDelivery;
import legumes.shared.domain.LatLng;
import legumes.shared.domain.Menu;
import legumes.shared.domain.MenuCount;
import legumes.shared.domain.MenuItem;
import legumes.shared.domain.OnSaleProduct;
import legumes.shared.domain.Order;
import legumes.shared.domain.OrderPart;
import legumes.shared.domain.OrderPartMenuItem;
import legumes.shared.domain.PaiementModeEnum;
import legumes.shared.domain.PlaceDelivery;
import legumes.shared.domain.PostalAdress;
import legumes.shared.domain.Price;
import legumes.shared.domain.Product;
import legumes.shared.domain.ProductCategory;
import legumes.shared.domain.ProductVariety;
import legumes.shared.domain.Quantity;
import legumes.shared.domain.SellSession;
import legumes.shared.domain.Stall;
import legumes.shared.domain.Store;
import legumes.shared.domain.Unit;

import org.jBCrypt.BCrypt;

import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyService;

public class GaeInitDB {

	public GaeInitDB() {
		
	}
	
	public void initDB(){
		Objectify ofy = ObjectifyService.begin();
		//### USERS
		ofy.put( createAdminCustomer() );
		//### PRODUCTS
		createProductVarietiesAndCategories(ofy);
		long dMenuDate = new Date(2011, 01, 12, 21, 18, 9).getTime();
		
		//because we search the products created above
		//and to be sure to retrieve them, we restart the service
		ofy = ObjectifyService.begin();
		Menu menu = createMenu(dMenuDate);
		MenuItem menuItem = createMenuIem();
		menu.addMenuWholeItem(menuItem);
		MenuItem menuItem2 = createMenuIem2();
		menu.addMenuHalfItem( menuItem2 );
//		ofy.put(menu);
		ofy.put( createorder(menu, menuItem) );
		
		Stall stall = new Stall();
		stall.setSellSessionDate(dMenuDate);
		stall.setMenu(menu);
//		ofy.put( stall );
		
		ofy.put( createSellSession(dMenuDate, stall, menu) );
		ofy.put( createStore() );
		
		ofy.put( createStore2() );
		
	}
	
	private Store createStore(){
		Store s = new Store();
		s.setId(1);
		s.setOpened(true);
		s.setCustomerId("root@root.fr");
		s.setStoreName("Aux délicieuses spécialités de l'Aveyron");
		s.setMessage("Store message...");
		s.addPlaceDelivery(createPlaceDelivery(s.getStoreName()));
		s.addPlaceDelivery(createPlaceDelivery2(s.getStoreName()));
		s.addPlaceDelivery(createHomePlaceDelivery(s.getStoreName()));
		s.getPaiementModes().addPaiementMode(PaiementModeEnum.MONNAIE, "");
		s.getPaiementModes().addPaiementMode(PaiementModeEnum.CHEQUE, "");
		s.getPaiementModes().addPaiementMode(PaiementModeEnum.TITRES_RESTAURANTS, "2 Maximum par commande.");
		
		return s;
	}
	
	private Store createStore2(){
		Store s = new Store();
		s.setId(2);
		s.setOpened(true);
		s.setCustomerId("root@root.fr");
		s.setStoreName("Aux délicieuses saveurs Toulousaines");
		s.setMessage("Store message...");
		s.addPlaceDelivery(createPlaceDelivery(s.getStoreName()));
		s.addPlaceDelivery(createPlaceDelivery2(s.getStoreName()));
		s.addPlaceDelivery(createHomePlaceDelivery(s.getStoreName()));
		
		s.getPaiementModes().addPaiementMode(PaiementModeEnum.MONNAIE, "");
		s.getPaiementModes().addPaiementMode(PaiementModeEnum.CHEQUE, "1 justificatif d'identité devra être présenté.");
		s.getPaiementModes().addPaiementMode(PaiementModeEnum.TITRES_RESTAURANTS, "2 Maximum par commande.");
		s.getPaiementModes().addPaiementMode(PaiementModeEnum.AMERICAN_EXPRESS, "A partie de 20€ d'achats.");
		s.getPaiementModes().addPaiementMode(PaiementModeEnum.MASTER_CARD, "A partie de 20€ d'achats.");
		s.getPaiementModes().addPaiementMode(PaiementModeEnum.VISA, "A partie de 20€ d'achats.");
		s.getPaiementModes().addPaiementMode(PaiementModeEnum.MAESTRO, "A partie de 20€ d'achats.");
		
		return s;
	}
	
	private HomePlaceDelivery createHomePlaceDelivery(String storeName_) {
		HomePlaceDelivery hpd = new HomePlaceDelivery();
		hpd.setId(System.currentTimeMillis());
		hpd.setLatLng(new LatLng(43.60448, 1.44333));
		hpd.setRadiusKm(15);
		hpd.setTitle("Livraison sur Toulouse center");
		hpd.setPostalAddress(null);
		return hpd;
	}
	
	private PlaceDelivery createPlaceDelivery2(String storeName_) {
		PlaceDelivery pd = new PlaceDelivery();
		pd.setId(System.currentTimeMillis());
		pd.setLatLng(new LatLng(43.65717, 1.48358));
		pd.setTitle("Marché de l'Union");
		pd.setPostalAddress(createMailingAddress2(storeName_, pd.getTitle()));
		return pd;
	}
	
	private PlaceDelivery createPlaceDelivery(String storeName_) {
		PlaceDelivery pd = new PlaceDelivery();
		pd.setId(System.currentTimeMillis());
		pd.setLatLng(new LatLng(43.57947, 1.45944));
		pd.setTitle("Marché de Saouzelong");
		pd.setPostalAddress(createMailingAddress(storeName_, pd.getTitle()));
		return pd;
	}

	private PostalAdress createMailingAddress2(String storeName_, String title_) {
		PostalAdress ma = new PostalAdress();
		ma.setId(System.currentTimeMillis());
		ma.setAdressPrecision("Sur la place principale de Lunion a coté de l'église");
		ma.setCivility(CivilityEnum.Madam.name());
		ma.setCompanyName(storeName_);
		ma.setCountry("France");
		ma.setFirstName("Véronique");
		ma.setLastName("Savy");
		ma.setPhone1("061212121212");
		ma.setPlaceCalled(null);
		ma.setStreet("5 Avenue des Pyrénées");
		ma.setTown("L'union");
		ma.setZipCode("31240");
		
		return ma;
	}

	
	private PostalAdress createMailingAddress(String storeName_, String title_) {
		PostalAdress ma = new PostalAdress();
		ma.setId(System.currentTimeMillis());
		ma.setAdressPrecision("Devant le métro saouzelong.");
		ma.setCivility(CivilityEnum.Sir.name());
		ma.setCompanyName(storeName_);
		ma.setCountry("France");
		ma.setFirstName("Sylvain");
		ma.setLastName("Marty");
		ma.setPhone1("068112313112");
		ma.setPlaceCalled("Saouzelong");
		ma.setStreet("5 Avenue Albert bedouce");
		ma.setTown("Toulouse");
		ma.setZipCode("31400");
		
		return ma;
	}

	private SellSession createSellSession(long sellSessionCreationDate_, Stall stall, Menu menu){
		SellSession ss = new SellSession();
		ss.setCreationDate(sellSessionCreationDate_);
		ss.setStall(stall);
		return ss;
	}
	
	
	
	private Order createorder(Menu menu, MenuItem menuItem){
		//Root user create an order
		Order o = new Order();
		o.setId(1L);
		o.setCustomerId("root@root.fr");
		o.setCustomerName("Root");
		o.setDate(new Date(2011, 01, 12, 21, 18, 9).getTime());
		o.setOrderParts(null);
		
		List<OrderPart> l = new ArrayList<OrderPart>();
		OrderPart op = new OrderPart();
		op.setId(new Date(2011,01,12,21,04,59).getTime());
		
		//Root customer takes one menu
		OrderPartMenuItem opmi = new OrderPartMenuItem();
		opmi.setId(1);
		opmi.setMenu( menu );
		opmi.setMenuCount(MenuCount.ONE_MENU);
		op.setOrderPartMenuItem(opmi);
		
		//Root customer takes nothing else
//		List<OrderPartProductItem> oppiList = new ArrayList<OrderPartProductItem>();
//		OrderPartProductItem oppi = new OrderPartProductItem();
//		oppi.setId(menuItem.getId());
//		oppi.setQuantity(new Quantity(1f, Unit.KG));
////		OnSaleProduct osp = new OnSaleProduct();
//		//Todo
//		oppi.setOnSaleProduct(osp);
//		oppiList.add(oppi);
		
		l.add(op);
		o.setOrderParts(l);
		return o;
	}
	
	
	
	private MenuItem createMenuIem(){
		MenuItem mi = new MenuItem();
		mi.setId(1);
		
		mi.setOnSaleProduct( createOnSaleProduct("Battavia", null) );
		mi.setQuantity(new Quantity(1, Unit.KG.toString()));
		
		return mi;
	}
	
	private OnSaleProduct createOnSaleProduct(String productName_, Float price_){
		OnSaleProduct osp = new OnSaleProduct();
		osp.setId(new Date().getTime());
		
		osp.setProduct( DALLegumesServicesImpl.getInstance().getProductsStartingWith(productName_)[0] );
		if(price_!=null){
			createPrice(createQuantity(Unit.KG, 1f), 1.5f);
		}
		osp.setPrice(null);
		return osp;
	}
	
	private Price createPrice(Quantity qty_, float price_){
		Price p = new Price();
		p.setAmount(price_);
		p.setQuantity(qty_);
		return p;
		
	}
	private Quantity createQuantity(Unit u_, float qty_){
		Quantity qty = new Quantity();
		qty.setUnitAsEnum(u_);
		qty.setValue(qty_);
		return qty;
	}
	
	private MenuItem createMenuIem2(){
		MenuItem mi = new MenuItem();
		mi.setId(2);
		
		mi.setOnSaleProduct( createOnSaleProduct("Battavia", 0.70f) );
		mi.setQuantity(new Quantity(1, Unit.KG.toString()));
		
		return mi;
	}
	
	private Menu createMenu(long menuDate){
		Menu m = new Menu();
		m.setHalfPrice(7.0f);
		m.setWholePrice(14.0f);
		m.setDate(menuDate);
		
		return m;
	}
	
	private Customer createAdminCustomer(){
		Customer c = new Customer();
		c.setEmail("root@root.fr");
		c.setName("Root");
		c.setActivationAccountDate( System.currentTimeMillis() );
		String hashFromDB = BCrypt.hashpw("wkjfff", BCrypt.gensalt() );
		c.setPassword( hashFromDB );
		c.setRoles(CustomerRole.ADMINISTRATOR);
		c.setCreationDate(new Date(2011, 01, 01, 01, 01, 01).getTime());
		c.setLastConnectionDate(new Date(2011, 01, 01, 01, 01, 05).getTime());
		c.setLastConnectionAddr("127.0.0.1");
		return c;
	}
	
	private void createProductVarietiesAndCategories(Objectify ofy_){
		String [] productCategories = new String[]{
				"Vegetables", "Fruts"};
		
		String [] productVarietiesVegetables = new String[]{
				"Ail", 
				"Aubergine", 
				"Avocat", 
				"Basilic", 
				"Betterave",
				"Carotte",
				"Champignon",
				"Ciboulette",
				"Concombre",
				"Coriandre",
				"Courgettes",
				"Echalottes",
				"Haricots",
				"Lentilles",
				"Maïs",
				"Menthe",
				"Oignons",
				"Persil",
				"Poireau",
				"Pois",
				"Poivrons",
				"PommeDeTerre",
				"Potimarron",
				"Romarain",
				"Salade",
				"Tomate",
				"Salade"
		};
		String [] productVarietiesFruts = new String[]{
				"Abricot",  
				"Brugnon", 
				"Cassis", 
				"Chataigne",
				"Citron",   
				"Cerise",
				"Clementine",  
				"Coing",
				"Figue",
				"Fraise", 
				"Framboise",   
				"Groseille",
				"kiwi", 
				"Mandarine",
				"Melon",   
				"Mure", 
				"Myrtille", 
				"Nectarine", 
				"Noix",
				"Orange",  
				"Pasteque",
				"Peche",
				"Poire", 
				"Prune", 
				"Pommes",  
				"Raisin",
				"Rhubarbe"};
		for(String pcStr : productCategories){
			ProductCategory pc = new ProductCategory();
			pc.setName(pcStr);
			ofy_.put(pc);
			
			if(pc.getName().equalsIgnoreCase("Vegetables")){
				createProductVarieties(ofy_, pc, productVarietiesVegetables);
			} else if(pc.getName().equalsIgnoreCase("Fruts")){
				createProductVarieties(ofy_, pc, productVarietiesFruts);
			}
		}
	}
	
	private void createProductVarieties(
			Objectify ofy_,
			ProductCategory pc_,
			String [] productVarieties_
	){
		for(String pcStr : productVarieties_){
			ProductVariety pv = new ProductVariety();
			pv.setName(pcStr);
			pv.setProductCategory(pc_);
			ofy_.put(pv);
			
			String [] productSalades = new String[]{
					"Battavia", 
					"FeuilleDeChene"
			};
			String [] productPoires = new String[]{
					"Belle épine du Mas", 
					"Beurré Giffard", 
					"Williams", 
					"Pérouille", 
					"Guyot", 
					"Francois Guay"
			};
			String [] productPommes = new String[]{
					"Reinette du Canada", 
					"Pink Lady", 
					"Fuji", 
					"Gala", 
					"Golden"
			};
			
			if(pv.getName().equalsIgnoreCase("Salade")){
				createProductName(ofy_, pc_, pv, productSalades);
			} else if(pv.getName().equalsIgnoreCase("Poire")){
				createProductName(ofy_, pc_, pv, productPoires);
			} else if(pv.getName().equalsIgnoreCase("Pommes")){
				createProductName(ofy_, pc_, pv, productPommes);
			} 
			
		}
	}
	
	private void createProductName(
			Objectify ofy_,
			ProductCategory pc_,
			ProductVariety pv_,
			String [] productNames_
	){
		for(String pcStr : productNames_){
			Product pv = new Product();
			pv.setName(pcStr);
//			pv.setProductCategory(pc_);
			pv.setProductVariety(pv_);
			
			ofy_.put(pv);
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// This script is used to initialize the db
		// using Google App Engine
		
		new GaeInitDB().initDB();
		

	}

}
